home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / PASWIZ20 / PASWIZ.DOC < prev    next >
Text File  |  1994-11-04  |  50KB  |  1,398 lines

  1.                   The Pascal Wizard's Library
  2.                   =-------------------------=
  3.                           Version 2.0
  4.  
  5.     PasWiz  Copyright (c) 1990-1994  Thomas G. Hanlin III
  6.  
  7.  
  8.  
  9. This is PasWiz, a library of assorted routines for use with
  10. Turbo Pascal, Quick Pascal, and compatible compilers. The PasWiz
  11. collection is copyrighted, but may be distributed as long as the
  12. following conditions are met:
  13.  
  14.    All PasWiz files must be distributed together as a unit in
  15.    unmodified form. No files may be left out or added.
  16.  
  17. YOU USE THIS LIBRARY AT YOUR OWN RISK. It has been tested by me
  18. on my own computer, but I will not assume any responsibility for
  19. any problems which PasWiz may cause you.
  20.  
  21. Shareware operates on a "try before you buy" basis. It is
  22. expected that if you find PasWiz useful, you will register your
  23. copy. You may not use PasWiz routines in programs intended for
  24. distribution unless you have registered. Registration entitles
  25. you to receive full source code for PasWiz and a great many
  26. other products. See the ORDER.FRM file for details.
  27.  
  28.                       Table of Contents                  page 2
  29.  
  30.  
  31.  
  32.  Overview and Legal Info .................................... 1
  33.  
  34.  Archive Directories ........................................ 3
  35.  
  36.  BCD Math ................................................... 5
  37.  
  38.  Equipment Info ............................................. 9
  39.  
  40.  Expression Evaluator ...................................... 12
  41.  
  42.  Extensions to Pascal's Math ............................... 13
  43.  
  44.  Joystick Support .......................................... 15
  45.  
  46.  Keyboard Control .......................................... 16
  47.  
  48.  String Stuff .............................................. 20
  49.  
  50.  Music ..................................................... 24
  51.  
  52.  Mouse ..................................................... 25
  53.  
  54.                       Archive Directories                 page 3
  55.  
  56.                         Unit: Archives
  57.  
  58.  
  59.  
  60. When I started in the microcomputer industry, there was a small
  61. variety of file archivers, all (more or less) compatible. They
  62. did not provide compression, which was relegated to another
  63. large selection of more-or-less compatible utilities. Then came
  64. SEA's ARC. It was very slow, but it did compression as well as
  65. archiving, and included CRC checks so you could know whether the
  66. files were intact. It swept the BBS scene in short order,
  67. becoming the new standard. A few other archivers competed on
  68. about a level footing, providing only minor variances on the ARC
  69. theme. Then SEA decided to sue one of their more successful
  70. competitors, Phil Katz (PKARC). The end result was PKZIP, which
  71. totally blew ARC away-- a useful hint to companies that choose
  72. to litigate instead of innovate. In the chaos resulting from the
  73. breaking of the former ARC standard, many other archivers came
  74. into being: ARJ, LZH, PAK, ZOO, et al.
  75.  
  76. PBWiz helps resolve the confusion by providing a single set of
  77. routines which allow you to view the contents of archives in any
  78. of the above-mentioned formats: ARJ, LZH, PAK, ZIP, ZOO, and
  79. even the antique ARC protocol. It also handles self-extracting
  80. EXE files of the forms produced by ARJ, LHARC and ZIP2EXE. Only
  81. archive directories are provided at this time. Other formats
  82. will also be added as they arise. If you have details on the
  83. format of an archive that you'd like me to add to PBWiz, please
  84. send them my way.
  85.  
  86. Viewing archive directories is handled in roughly the same
  87. fashion as you might view a DOS file directory. This makes it
  88. possible to treat an archive and a subdirectory in a similar
  89. manner, as long as the archive doesn't contain archives itself.
  90.  
  91. When you're looking for the first file in an archive, use the
  92. FindFirstA function. You must specify the archive name and a
  93. file name. The archive name may include a drive and path
  94. specification, and does not need to have the archive extension.
  95. If you leave off the extension, FindFirstA will use the first
  96. archive it comes across that matches the rest of the
  97. specification. Note that the archive specification may not
  98. contain wildcards. In contrast, the search file name may not
  99. contain drive or path specs, but may contain wildcards.
  100.  
  101. PROCEDURE FindFirstA (ArchiveName, FileName: String;
  102.                       VAR ErrCode: Integer);
  103.  
  104.  
  105.                       Archive Directories                 page 4
  106.  
  107.                         Unit: Archives
  108.  
  109.  
  110.  
  111. If there are no files to be found, or if the archive
  112. specification was bad, an error code will be returned. If there
  113. was no error, there may well be more files to be found. You can
  114. find each of them with FindNextA:
  115.  
  116. FindNextA (VAR ErrCode: Integer);
  117.  
  118. Of course, just finding a matching file doesn't do you much good
  119. unless you can retrieve information about it. You can use any of
  120. the following routines to provide information about a matched
  121. file:
  122.  
  123. FUNCTION GetNameA: String;    { file name }
  124. FUNCTION GetDateA: String;    { file date }
  125. FUNCTION GetTimeA: String;    { file time (24-hour) }
  126. FUNCTION GetCRCA: String;     { file CRC (8-char hexadecimal) }
  127. FUNCTION GetStoreA: String;   { file storage method }
  128.  
  129. PROCEDURE GetSizeA (VAR OriginalSize: LongInt;
  130.                     VAR CurrentSize: LongInt);
  131.  
  132. When you're done viewing an archive, be sure to close it:
  133.  
  134. PROCEDURE CloseA;
  135.  
  136. Let's try an example, to view all files in an archive:
  137.  
  138.    USES
  139.       Archives;
  140.    VAR
  141.       ErrCode: Integer;
  142.    BEGIN
  143.       IF ParamCount = 1 THEN BEGIN
  144.          FindFirstA(ParamStr(1), '*.*', ErrCode)
  145.          WHILE ErrCode = 0 DO BEGIN
  146.             WriteLn(GetNameA);
  147.             FindNextA(ErrCode);
  148.          END;
  149.          CloseA;
  150.       END
  151.       ELSE
  152.          WriteLn('Archive name expected');
  153.    END.
  154.  
  155.                            BCD Math                      page 5
  156.  
  157.                            Unit: BCD
  158.  
  159.  
  160.  
  161. Some of you may not have heard of BCD math, or at least not have
  162. more than a passing acquaintance with the subject. BCD (short
  163. for Binary-Coded Decimal) is a way of encoding numbers. It
  164. differs from the normal method of handling numbers in several
  165. respects. On the down side, BCD math is much slower than normal
  166. math and the numbers take up more memory. However, the benefits
  167. may far outweigh these disadvantages, depending on your
  168. application: BCD math is absolutely precise within your desired
  169. specifications, and you can make a BCD number as large as you
  170. need. If your applications don't require great range or
  171. precision out of numbers, normal Pascal math is probably the
  172. best choice. For scientific applications, accounting,
  173. engineering and other demanding tasks, though, BCD may be just
  174. the thing you need.
  175.  
  176. The BCD math routines provided by PasWiz allow numbers of up to
  177. 255 digits long (the sign counts as a digit, but the decimal
  178. point doesn't). You may set the decimal point to any position
  179. you like, as long as there is at least one digit position to the
  180. left of the decimal.
  181.  
  182. Since Pascal doesn't support BCD numbers directly, we store the
  183. BCD numbers in strings. The results are not in text format and
  184. won't mean much if displayed. A conversion routine allows you to
  185. change a BCD number to a text string in any of a variety of
  186. formats.
  187.  
  188. Note that the BCD math handler doesn't yet track
  189. overflow/underflow error conditions. If you anticipate that this
  190. may be a problem, it would be a good idea to screen your input
  191. or to make the BCD range large enough to avoid these errors.
  192.  
  193. Let's start off by considering the BCD range. This is kept in
  194. two integer variables, LDigits and RDigits, which can be
  195. accessed by your program. These variables specify the maximum
  196. number of digits to the left and to the right of the decimal
  197. point. There must be at least one digit on the left, and the
  198. total number of digits must be less than 255. The BCD strings
  199. will have a length that's one larger than the total number of
  200. digits, to account for the sign of the number. The decimal point
  201. is implicit and doesn't take up any extra space.
  202.  
  203. It is assumed that you will only use one size of BCD number in
  204. your program-- there are no provisions for handling mixed-length
  205. BCD numbers. Of course, you could manage that yourself with a
  206. little extra work, if it seems like a useful capability. If you
  207. don't change LDigits or RDigits, the default size of the BCD
  208. numbers will be 32 (20 to the left, 11 to the right, 1 for the
  209. sign).
  210.  
  211.                            BCD Math                      page 6
  212.  
  213.                            Unit: BCD
  214.  
  215.  
  216.  
  217. Before doing any BCD calculations, you must have some BCD
  218. numbers! The BCDSet routine takes a number in text string form
  219. and converts it to BCD:
  220.  
  221. TextSt := '1234567890.50';
  222. Nr := BCDSet(TextSt);
  223.    { FUNCTION BCDSet (TextSt: String): String; }
  224.  
  225. If your numbers are stored as actual numbers, you can convert
  226. them to a text string with Pascal's Str procedure, then to BCD:
  227.  
  228. Str(Number, TextSt);
  229. Nr := BCDSet(TextSt);
  230.  
  231. BCD numbers can also be converted back to text strings, of
  232. course. You may specify how many digits to the right of the
  233. decimal to keep (the number will be truncated, not rounded). If
  234. the RightDigits value is positive, trailing zeros will be kept;
  235. if negative, trailing zeros will be removed. There are also
  236. various formatting options which may be used. Here's how it
  237. works:
  238.  
  239. FUNCTION BCDFormat (Nr: String; HowToFormat,
  240.                     RightDigits: Integer): String;
  241.  
  242. The HowToFormat value may be any combination of the following
  243. (just add the numbers of the desired formats together):
  244.  
  245.    0   plain number
  246.    1   use commas to separate thousands, etc
  247.    2   start number with a dollar sign
  248.    4   put the sign on the right instead of the left side
  249.    8   use plus sign instead of space if nr is not negative
  250.  
  251. The BCD math functions are pretty much self-explanatory, so I'll
  252. keep the descriptions brief. The single-parameter functions are
  253. listed on the next page.
  254.  
  255.                            BCD Math                      page 7
  256.  
  257.                            Unit: BCD
  258.  
  259.  
  260.  
  261. { absolute value }
  262. FUNCTION BCDAbs (Nr: String): String;
  263.  
  264. { cosine }
  265. FUNCTION BCDCos (Nr: String): String;
  266.  
  267. { cotangent }
  268. FUNCTION BCDCot (Nr: String): String;
  269.  
  270. { cosecant }
  271. FUNCTION BCDCsc (Nr: String): String;
  272.  
  273. { convert degrees to radians }
  274. FUNCTION BCDDeg2Rad (Nr: String): String;
  275.  
  276. { the constant "e" }
  277. FUNCTION BCDe: String;
  278.  
  279. { factorial }
  280. FUNCTION BCDFact (Nr: Integer): String;
  281.  
  282. { fractional part of number }
  283. FUNCTION BCDFrac (Nr: String): String;
  284.  
  285. { integer part of number }
  286. FUNCTION BCDInt (Nr: String): String;
  287.  
  288. { negation }
  289. FUNCTION BCDNeg (Nr: String): String;
  290.  
  291. { the constant "pi" }
  292. FUNCTION BCDpi: String;
  293.  
  294. { convert radians to degrees }
  295. FUNCTION BCDRad2Deg (Nr: String): String;
  296.  
  297. { secant }
  298. FUNCTION BCDSec (Nr: String): String;
  299.  
  300. { signum }
  301. FUNCTION BCDSgn (Nr: String): Integer;
  302.  
  303. { sine }
  304. FUNCTION BCDSin (Nr: String): String;
  305.  
  306. { square root }
  307. FUNCTION BCDSqrt (Nr: String): String;
  308.  
  309. { tangent }
  310. FUNCTION BCDTan (Nr: String): String;
  311.  
  312.                            BCD Math                      page 8
  313.  
  314.                            Unit: BCD
  315.  
  316.  
  317.  
  318. Notes on the single-parameter functions:
  319.  
  320.   The signum function returns an integer based on the sign of
  321.   the BCD number:
  322.  
  323.      -1   if the BCD number is negative
  324.       0   if the BCD number is zero
  325.       1   if the BCD number is positive
  326.  
  327.   BCDpi is accurate to the maximum level afforded by the BCD
  328.   functions. BCDe is accurate to as many as 115 decimal places.
  329.   The actual accuracy, of course, depends on the size of BCD
  330.   numbers you've chosen.
  331.  
  332.   The trigonometric functions (cos, sin, tan, sec, csc, cot)
  333.   expect angles in radians. BCDDeg2Rad and BCDRad2Deg will allow
  334.   you to convert back and forth between radians and degrees.
  335.  
  336.  
  337.  
  338. Here is a list of the two-parameter functions:
  339.  
  340.  
  341. { addition }
  342. FUNCTION BCDAdd (Nr1, Nr2: String): String;
  343.  
  344. { divide 1st by 2nd }
  345. FUNCTION BCDDiv (Nr1, Nr2: String): String;
  346.  
  347. { multiplication }
  348. FUNCTION BCDMul (Nr1, Nr2: String): String;
  349.  
  350. { subtract 2nd from 1st }
  351. FUNCTION BCDSub (Nr1, Nr2: String): String;
  352.  
  353. { raise to a power }
  354. FUNCTION BCDPower (Nr: String; Power: Integer): String;
  355.  
  356. { compare two numbers }
  357. FUNCTION BCDCompare (Nr1, Nr2: String): Integer;
  358.  
  359. The comparison function returns an integer which reflects how
  360. the two numbers compare to each other:
  361.  
  362.    -1   Nr1 < Nr2
  363.     0   Nr1 = Nr2
  364.     1   Nr1 > Nr2
  365.  
  366.                         Equipment Info                   page 9
  367.  
  368.                         Unit: Equipment
  369.  
  370.  
  371.  
  372. The equipment unit gives you information about the computing
  373. environment. This includes both installed software and hardware.
  374.  
  375. The first function allows you to determine if an "enhanced"
  376. keyboard (101-key) is installed. It may not be able to figure
  377. out what the keyboard is on some older not-quite-clone PCs, in
  378. which case it will take the safe way out and report that there
  379. is no enhanced keyboard. This function returns -1 if there is an
  380. enhanced keyboard present, 0 if not.
  381.  
  382. FUNCTION EnhKbd: Integer;
  383.  
  384. Want to know the type of processor (CPU) being used? Can do!
  385.  
  386. FUNCTION Processor: Integer;
  387.  
  388. The results will be reported as a number which can be decoded as
  389. follows:
  390.  
  391.    0    NEC V20
  392.    1    8088 or 8086
  393.    2    80186
  394.    3    80286
  395.    4    80386
  396.    5    80486
  397.  
  398. Maybe you'd like to check for a CD-ROM drive:
  399.  
  400. FUNCTION CDROM: Integer;
  401.  
  402. This tells you how many logical drives exist, if there is a
  403. CD-ROM available. If not, it will return 0. Note that the CD-ROM
  404. installation check conflicts with the GRAPHICS.COM installation
  405. check for DOS 4.0, due to some screw-up at IBM or Microsoft. I'm
  406. not yet sure whether DOS 5.0 is similarly afflicted.
  407.  
  408. The number of floppy drives installed is retrieved with this:
  409.  
  410. FUNCTION Floppies: Integer;
  411.  
  412. To get the number of serial (COM) ports and parallel (LPT)
  413. ports, use the following functions:
  414.  
  415. FUNCTION CommPorts: Integer;
  416.  
  417. FUNCTION PrtPorts: Integer;
  418.  
  419.                         Equipment Info                  page 10
  420.  
  421.                         Unit: Equipment
  422.  
  423.  
  424.  
  425. Now, there may be up to four floppy drives in a system; however,
  426. the AT CMOS data area only directly supports two. This makes it
  427. easy to find out what kind of drives the first two are, but not
  428. the second two, if any. Such is life.
  429.  
  430. PROCEDURE FloppyType (VAR Drive1, Drive2: Integer);
  431.  
  432. The results from FloppyType are returned as follows:
  433.  
  434.    0    no drive
  435.    1    5 1/4"    360K
  436.    2    5 1/4"    1.2M
  437.    3    3 1/2"    720K
  438.    4    3 1/2"    1.44M
  439.    5    3 1/2"    2.88M
  440.  
  441. Result codes of 6-7 are also available, but are not yet defined.
  442.  
  443. New memory types sure have burgeoned over the years... expanded,
  444. extended, and now XMS. There are routines to check all of these:
  445.  
  446. { amount of extended memory installed }
  447. FUNCTION AllExtMem: LongInt;
  448.  
  449. { BIOS extended memory available }
  450. FUNCTION GetExtM: LongInt
  451.  
  452. { amount of expanded memory  (a page is 16 Kbytes) }
  453. PROCEDURE GetEMSm (VAR TotalPages, FreePages: Integer);
  454.  
  455. { amount of XMS memory  (returned in kilobytes) }
  456. PROCEDURE GetXMSm (VAR LargestFreeBlock, TotalFree: LongInt);
  457.  
  458. When you're dealing with extended memory, whether it be
  459. BIOS-type or using the XMS standard, the results are returned in
  460. kilobytes. Multiply 'em by 1024 to convert to bytes. When you're
  461. dealing with expanded memory (EMS), the results are in pages of
  462. 16,384 bytes.
  463.  
  464.                         Equipment Info                  page 11
  465.  
  466.                         Unit: Equipment
  467.  
  468.  
  469.  
  470. A few more routines to get the versions of the EMS and XMS
  471. drivers, if any:
  472.  
  473. PROCEDURE GetEMSv (VAR MajorV, MinorV: Integer);
  474.  
  475. PROCEDURE GetXMSv (VAR MajorV, MinorV: Integer);
  476.  
  477. These return the major and minor version numbers as two separate
  478. integers. For example, EMS 4.0 would return major version 4,
  479. minor version 0.
  480.  
  481. It's nice to know a little about the operating environment. With
  482. the below routines, you can find out what the DOS version is;
  483. what version of 4DOS, if any, is in use; and whether Microsoft
  484. Windows is running.
  485.  
  486. PROCEDURE GetDOSv (VAR MajorV, MinorV: Integer);
  487.  
  488. PROCEDURE Get4DOSv (VAR MajorV, MinorV: Integer);
  489.  
  490. PROCEDURE WinCheck (VAR MajorV, MinorV: Integer);
  491.  
  492. These return results as major and minor version numbers, as
  493. discussed above. The Get4DOSv and WinCheck routines return
  494. zeroes if 4DOS and Windows, respectively, are not in use.
  495.  
  496. There are a couple of curious features of GetDOSv to keep in
  497. mind. If the version is 10 or higher, you're running under OS/2.
  498. DOS version 10 is actually OS/2 1.0, version 20 is OS/2 2.0, and
  499. so on. Secondly, if you're using DOS 5.0, the version reported
  500. may not be 5.0-- DOS 5.0 can be told to reply with a lower
  501. version number to allow badly written older software to run
  502. properly.
  503.  
  504. One final routine that should be of some value is the one that
  505. allows you to find out what kind of display is available. It
  506. tells you the specific adapter and whether the display is color
  507. or monochrome. There is one case in which it can be confused,
  508. however-- if the adapter is CGA, the display is assumed to be
  509. color, since there is no way for the computer to know any
  510. differently. So, although this routine provides a good idea of
  511. what is available, it would be a good idea to provide an option
  512. to tell the program that a monochrome display is attached.
  513. Microsoft normally uses "/B" for this purpose, so that might be
  514. a good standard to stick with.
  515.  
  516. PROCEDURE GetDisplay (VAR Adapter: Integer; VAR Mono: Boolean);
  517.  
  518. The adapter will be one of the following:
  519.  
  520.    1     MDA                  4     EGA
  521.    2     Hercules             5     MCGA
  522.    3     CGA                  6     VGA
  523.  
  524.                      Expression Evaluator               page 12
  525.  
  526.                          Unit: ExtMath
  527.  
  528.  
  529.  
  530. The expression evaluator solves numeric equations. It allows you
  531. to find the result of an expression contained in a string.
  532. Normal algebraic precedence is used, e.g. 4+3*5 evaluates to 19.
  533. The usual numeric operators (*, /, +, -, ^) are supported
  534. (multiply, divide, add, subtract, and raise to a power).
  535. Negation is also supported. Parentheses can be used for
  536. overriding the default order of operations.
  537.  
  538. You may use either double asterisk ("**") or caret ("^") symbols
  539. to indicate exponentiation.
  540.  
  541. The constant PI is recognized, as are the following functions:
  542.    ABS    absolute value        INT    integer
  543.    ACOS   inverse cosine        LOG    natural log
  544.    ASIN   inverse sine          SIN    sine
  545.    ATAN   inverse tangent       SQRT   square root
  546.    COS    cosine                TAN    tangent
  547.    FRAC   fraction
  548.  
  549. Functions should not be nested.
  550.  
  551. Trig functions expect angles in radians.
  552.  
  553. To evaluate an expression, you pass it to the evaluator as a
  554. string. You will get back either an error code or a real result.
  555. See the CALC.PAS program for a working example.
  556.  
  557. PROCEDURE Evaluate (Expression: String; VAR Result: Real;
  558.                     VAR ErrCode: Integer);
  559.  
  560. An expression evaluator adds convenience to any program that
  561. needs to accept numbers. Why make someone reach for a calculator
  562. when number crunching is what a computer does best?
  563.  
  564.                  Extensions to Pascal's Math            page 13
  565.  
  566.                         Unit: ExtMath
  567.  
  568.  
  569.  
  570. For the most part, the math routines in this library are
  571. designed to provide alternatives to the math routines that come
  572. with Pascal. Still, Pascal's own math support is quite adequate
  573. for many purposes, so there's no sense in ignoring it. Here are
  574. some functions which improve on Pascal's math.
  575.  
  576. { inverse cosine }
  577. FUNCTION ArcCos (Number: Real): Real;
  578.    { 1.0 >= Number >= -1.0 }
  579.  
  580. { inverse hyperbolic cosine }
  581. FUNCTION ArcCosH (Number: Real): Real;
  582.  
  583. { inverse cotangent }
  584. FUNCTION ArcCot (Number: Real): Real;
  585.  
  586. { inverse hyperbolic cotangent }
  587. FUNCTION ArcCotH (Number: Real): Real;
  588.  
  589. { inverse cosecant }
  590. FUNCTION ArcCsc (Number: Real): Real;
  591.  
  592. { inverse hyperbolic cosecant }
  593. FUNCTION ArcCscH (Number: Real): Real;
  594.  
  595. { inverse secant }
  596. FUNCTION ArcSec (Number: Real): Real;
  597.  
  598. { inverse hyperbolic secant }
  599. FUNCTION ArcSecH (Number: Real): Real;
  600.  
  601. { inverse sine }
  602. FUNCTION ArcSin (Number: Real): Real;
  603.    { 1.0 >= Number >= -1.0 }
  604.  
  605. { inverse hyperbolic sine }
  606. FUNCTION ArcSinH (Number: Real): Real;
  607.  
  608. { inverse hyperbolic tangent }
  609. FUNCTION ArcTanH (Number: Real): Real;
  610.  
  611. { ceiling: smallest integer >= specified number }
  612. FUNCTION Ceil (Number: Real): Real;
  613.  
  614. { hyperbolic cosine }
  615. FUNCTION CosH (Number: Real): Real;
  616.  
  617. { cotangent }
  618. FUNCTION Cot (Number: Real): Real;
  619.  
  620.                  Extensions to Pascal's Math            page 14
  621.  
  622.                         Unit: ExtMath
  623.  
  624.  
  625.  
  626. { cosecant }
  627. FUNCTION Csc (Number: Real): Real;
  628.  
  629. { convert degrees to radians }
  630. FUNCTION Deg2Rad (Number: Real): Real;
  631.  
  632. { the constant "e" }
  633. FUNCTION e: Real;
  634.  
  635. { error function }
  636. FUNCTION Erf (Number: Real): Real;
  637.  
  638. { factorial }
  639. FUNCTION Fact (Number: Integer): Real;
  640.  
  641. { floor: largest integer <= specified number }
  642. FUNCTION Floor (Number: Real): Real;
  643.  
  644. { log (base 10) }
  645. FUNCTION Log (Number: Real): Real;
  646.  
  647. { convert radians to degrees }
  648. FUNCTION Rad2Deg (Number: Real): Real;
  649.  
  650. { raise a number to a power }
  651. FUNCTION Raise (Number: Real; Power: Integer): Real;
  652.  
  653. { secant }
  654. FUNCTION Sec (Number: Real): Real;
  655.  
  656. { hyperbolic secant }
  657. FUNCTION SecH (Number: Real): Real;
  658.  
  659. { signum (integer) }
  660. FUNCTION SgnI (Number: Integer): Integer);
  661.  
  662. { signum (real) }
  663. FUNCTION SgnR (Number: Real): Integer);
  664.  
  665. { hyperbolic sine }
  666. FUNCTION SinH (Number: Real): Real;
  667.  
  668. { tangent }
  669. FUNCTION Tan (Number: Real): Real;
  670.  
  671. { hyperbolic tangent }
  672. FUNCTION TanH (Number: Real): Real;
  673.  
  674.                        Joystick Support                 page 15
  675.  
  676.                         Unit: Joystick
  677.  
  678.  
  679.  
  680. There's little enough to say about the joystick. A PC may have
  681. up to two of them. Normally, a joystick has two buttons, and
  682. returns a pair of coordinates which describe the position in
  683. which it is being held. The coordinates vary depending on the
  684. individual joystick, the computer involved, and other factors,
  685. so it is wise to provide a calibration routine to customize your
  686. program for the joystick(s) involved.
  687.  
  688. The FlightStick joystick has a dial for throttle control, which
  689. is available only in a one-joystick setup. The throttle value is
  690. returned as the Y coordinate of an imaginary second joystick.
  691.  
  692. Coordinates (X, Y), where X is the horizontal and Y the vertical
  693. coordinate, range from around 0 to around 150 on my FlightStick.
  694. Since these values may vary significantly, however, they are
  695. returned as words.
  696.  
  697. The state of the joystick buttons may be checked individually or
  698. all at once. If you need to know the state of multiple buttons,
  699. it is faster to do it all at once, but you may do it either way.
  700.  
  701. FUNCTION ButtonA1: Boolean;       { button 1 on 1st joystick }
  702. FUNCTION ButtonA2: Boolean;       { button 2 on 1st joystick }
  703. FUNCTION ButtonB1: Boolean;       { button 1 on 2nd joystick }
  704. FUNCTION ButtonB2: Boolean;       { button 2 on 2nd joystick }
  705.  
  706. PROCEDURE Buttons (VAR A1, A2, B1, B2: Boolean); { all buttons }
  707.  
  708. The joystick positions are handled internally by a rather
  709. unfortunate method involving a timer, due to the way IBM
  710. designed the joystick interface. This makes getting the position
  711. rather slow. To alleviate the problem, all positions are
  712. returned at once.
  713.  
  714. PROCEDURE Positions (VAR AX, AY, BX, BY: Word);
  715.  
  716. Joystick support is handled through a set of BIOS routines which
  717. were added to the PC around 1985. These routines are not present
  718. in some of the oldest PCs.
  719.  
  720.                        Keyboard Control                 page 16
  721.  
  722.                         Unit: Keyboard
  723.  
  724.  
  725.  
  726. The keyboard is not a particularly exciting or glamorous device.
  727. In fact, we tend to forget about it except when it gets in the
  728. way. Sometimes it's a hardware problem-- squishy or clacking
  729. keys, or perhaps a commonly-used key placed in an out-of-the-way
  730. location. Then again, sometimes it's the software that's the
  731. problem. There are many aspects of keyboard control, not all of
  732. which are necessarily related to input. This unit will let you
  733. handle the keyboard in ways you may not have realized were
  734. possible. Better yet, it can help make keyboard control easier
  735. than the users of your programs dreamed possible.
  736.  
  737. Let's start out with keyboard output. Yep, not input-- output.
  738. We can stuff up to 15 keys into the keyboard buffer. Why would
  739. we ever want to do this? Perhaps to allow your program to pop-up
  740. a TSR automatically, to start another program after your program
  741. ends, or for creating key macros. You can enter extended key
  742. codes (like function keys) by using CHR$(0) before the scan
  743. code.
  744.  
  745. PROCEDURE TypeIn (Keys: String);
  746.  
  747. The usual keyboard action is quite sluggish. We can make it a
  748. lot crisper by changing the key repeat rate and the delay before
  749. repeating. This will work on ATs, but not PC/XT systems.
  750.  
  751. PROCEDURE SpeedKey (RepDelay, RepRate: Integer);
  752.  
  753. The delay may be 0-3 (1 by default):
  754.  
  755.    0      250 milliseconds
  756.    1      500 milliseconds
  757.    2      750 milliseconds
  758.    3        1 second
  759.  
  760. The repeat rate may be 0-31 (11 by default). The larger the
  761. number, the slower the speed-- 0 is around 30 cps, and 31 is
  762. around 2 cps.
  763.  
  764. I generally prefer to have the keyboard cranked up to full
  765. speed, using RepDelay and RepRate both set to zero. This may be
  766. a bit too zippy for some people, and may cause keyboard buffer
  767. overflows with some games. Experiment with it to see what you
  768. like best.
  769.  
  770. Of course, there may be reasons to make keyboard repeat less
  771. sensitive instead! That might be a good idea in programs written
  772. for small children, for example. You can adjust the keyboard
  773. equally well in either direction.
  774.  
  775.                        Keyboard Control                 page 17
  776.  
  777.                         Unit: Keyboard
  778.  
  779.  
  780.  
  781. Pascal allows you to control one of the keys which can interrupt
  782. your program, namely the Break key. There's another dangerous
  783. key which PasWiz allows you to control-- the PrtSc (PrintScreen)
  784. key. PrtSc may not seem like a hazard at first glance, but if
  785. it's pressed by accident with no printer ready, or in a graphics
  786. mode which PrtSc doesn't understand how to print, the results
  787. can be pretty messy. So, we let you turn it off or on:
  788.  
  789. PROCEDURE SetPrtSc (PrtScON: Boolean);
  790.  
  791. Use FALSE to turn it off or TRUE to turn it back on. If you turn
  792. off PrtSc, you MUST remember to turn it back on again before
  793. your program ends! Otherwise, an interrupt vector will point
  794. into nowhere, causing probable chaos the next time PrtSc is
  795. pressed.
  796.  
  797. Regardless of whether you've turned the PrtSc key off, you can
  798. print the screen yourself just as if PrtSc had been pressed:
  799.  
  800. PROCEDURE PrintScreen;
  801.  
  802. Now here's a strange one for you. When IBM brought out the
  803. 101-key keyboard, called the "enhanced" keyboard, they did
  804. something bizarre to the BIOS. They still allowed old keyboard
  805. calls to work, but they filtered out the new key codes so no one
  806. would see them. This made sure that no one would be able to use
  807. the capabilities of the "enhanced" keyboard without rewriting
  808. their programs. So, the keyboard has been around for years, and
  809. there are still few programs that even notice when you press
  810. F11. Pascal does not support the enhanced keyboard at all.
  811. Fortunately, PasWiz -does-. You can find out if an enhanced
  812. keyboard is installed with the EnhKbd function, which is in the
  813. Equipment unit.
  814.  
  815. If there is an enhanced keyboard installed, you can activate it
  816. with this:
  817.  
  818. PROCEDURE SetEnhKbd (Enhanced: Boolean);
  819.  
  820. With enhanced keyboard support activated, all key requests that
  821. used the old services are translated to the new services. So,
  822. SetEnhKbd affects the ReadKey (in the CRT unit that comes with
  823. Pascal) and other Pascal functions as well as other PasWiz
  824. keyboard routines. Note that you MUST deactivate enhanced
  825. keyboard support before ending your program. Otherwise, an
  826. interrupt vector will point into nowhere, probably causing a
  827. crash on the next keypress!
  828.  
  829.                        Keyboard Control                 page 18
  830.  
  831.                         Unit: Keyboard
  832.  
  833.  
  834.  
  835. If you're about to request important input, you may not want to
  836. chance having it answered from results of the keyboard buffer--
  837. could be that the user meant those keys for another purpose. In
  838. that case, it's a good approach to clear out the keyboard buffer
  839. just before the input:
  840.  
  841. PROCEDURE ClearKbd;
  842.  
  843. No keyboard unit would be complete without a selection of
  844. routines to check the shift states and get or set the keyboard
  845. toggles. Let's start with the toggles, which are so called
  846. because they get toggled from one state to another:
  847.  
  848. FUNCTION CapsOn: Boolean;         { Caps Lock }
  849.  
  850. FUNCTION InsertOn: Boolean;       { Insert }
  851.  
  852. FUNCTION NumOn: Boolean;          { Num Lock }
  853.  
  854. FUNCTION ScrollOn: Boolean;       { Scroll Lock }
  855.  
  856. You can also turn the toggles off or on. It's courteous to
  857. restore the original toggle states once you end your program, so
  858. you might want to save the original values for that purpose.
  859. Then again, I guess that doesn't apply if your program is
  860. designed for the specific purpose of setting the toggles!
  861.  
  862. PROCEDURE SetCaps (CapsLock: Boolean);        { Caps Lock }
  863.  
  864. PROCEDURE SetInsert (InsertKey: Boolean);     { Insert }
  865.  
  866. PROCEDURE SetNum (NumLock: Boolean);          { Num Lock }
  867.  
  868. PROCEDURE SetScroll (ScrollLock: Boolean);    { Scroll Lock }
  869.  
  870. Does anyone actually use ScrollLock for anything?  Just
  871. curious...
  872.  
  873.                        Keyboard Control                 page 19
  874.  
  875.                         Unit: Keyboard
  876.  
  877.  
  878.  
  879. The shift keys are unique in many respects. They don't return
  880. codes that can be detected with ReadKey or stuffed into the
  881. keyboard buffer; several can be pressed at the same time; and
  882. they don't repeat. You can detect 'em with PasWiz, at any rate:
  883.  
  884. FUNCTION AltPress: Boolean;         { any ALT }
  885.  
  886. FUNCTION CtrlPress: Boolean;        { any CTRL }
  887.  
  888. FUNCTION ShiftPress: Boolean;       { any SHIFT }
  889.  
  890. FUNCTION LAltPress: Boolean;        { left ALT }
  891.  
  892. FUNCTION LCtrlPress: Boolean;       { left CTRL }
  893.  
  894. FUNCTION LShiftPress: Boolean;      { left SHIFT }
  895.  
  896. FUNCTION RAltPress: Boolean;        { right ALT }
  897.  
  898. FUNCTION RCtrlPress: Boolean;       { right CTRL }
  899.  
  900. FUNCTION RShiftPress: Boolean;      { right SHIFT }
  901.  
  902. NOTE that LAltPress, LCtrlPress, RAltPress, and RCtrlPress are
  903. ONLY available for enhanced keyboards. They will not return
  904. useful results on older keyboards.
  905.  
  906.                          String Stuff                   page 20
  907.  
  908.                          Unit: Strings
  909.  
  910.  
  911.  
  912. Strings have always been something of an afterthought in Pascal.
  913. This unit brings in the heavy artillery! The PasWiz string
  914. routines may be divided into the following categories:
  915. comparison, compression, encryption, extraction, searching, and
  916. miscellaneous (mostly alteration). Let's take up these
  917. categories one at a time.
  918.  
  919. The compression routines are designed to work with ordinary text
  920. strings. The strings may not contain IBM extended-ASCII codes
  921. (CHR($80)-CHR($FF)), as these are used in the compression.
  922. Compression works on spaces, which will give you an average of
  923. 15% compression on normal text. If you compress printable text
  924. (i.e., no control codes), you'll get printable text in return,
  925. which makes these routines handy for use with text files.
  926. Compression and decompression is done at an extreme rate of
  927. speed and will not affect the timing of your program in any
  928. noticeable fashion.
  929.  
  930. FUNCTION Bsq (St: String): String;     { compress a string }
  931.  
  932. FUNCTION BUsq (St: String): String;    { uncompress a string }
  933.  
  934. Comparing two strings is easy enough in Pascal, but not as
  935. flexible as might be desired for some applications. You can tell
  936. if two strings match exactly, but not if they're reasonably
  937. close matches. PasWiz has two fuzzy comparison routines which
  938. can help.
  939.  
  940. The Soundex routine uses a long-established algorithm to
  941. convert a word into a code which represents the sound of the
  942. word. It is fast and can work well under properly defined
  943. circumstances; for instance, it will tell you that "Smith"
  944. sounds just like "Smythe", but not like "Banks". Between the
  945. need for speed and the vagaries of the English language,
  946. however, you may find matches which don't work as well. Soundex
  947. is certain that "Knight" sounds just like "Smashed", for
  948. example. So, it may be perfect for something like a phone book,
  949. but not for a spelling checker!
  950.  
  951. FUNCTION Soundex (St: String): String;
  952.  
  953. The Bickel routine, on the other hand, tells you how closely two
  954. words match. This is a relative measure, not an absolute
  955. measure, so you'd probably want to search through an entire
  956. dictionary and just keep the words which matched best. The
  957. Bickel algorithm is slower than Soundex but is much more
  958. precise.
  959.  
  960. FUNCTION Bickel (St1, St2: String): Integer;
  961.  
  962.                          String Stuff                   page 21
  963.  
  964.                          Unit: Strings
  965.  
  966.  
  967.  
  968. There are many cases in which you might want to keep data
  969. private. The PasWiz encryption routines provide a simple and
  970. extremely fast method for password-protecting text. The
  971. encryption technique is trivial and will not withstand any
  972. concerted attack, but should suffice for casual use. It will
  973. help if you pick a longish password of unusual characters, for
  974. example '[^.mE@@&o}' (don't use this example itself, please)!
  975.  
  976. There are two encryption routines (which also work as decryption
  977. routines). The first is designed to produce printable, if
  978. bizarre-looking, results which are suited for use with text
  979. files. Text to be encrypted by this routine may not include IBM
  980. extended-ASCII characters (CHR($80) - CHR($FF)), since these are
  981. used to insure printable text.
  982.  
  983. FUNCTION CipherP (St, Passwd: String): String;
  984.  
  985. The other routine will work with any sort of text, but is not
  986. guaranteed to produce printable results. So, it's not suited for
  987. use with text files.
  988.  
  989. FUNCTION Cipher (St, Passwd: String): String;
  990.  
  991. Of the extraction routines, two are merely convenient
  992. rephrasings of the Copy function which allow you to grab a
  993. substring from the left or right side of a string:
  994.  
  995. FUNCTION Left (St: String; Len: Integer): String;
  996.  
  997. FUNCTION Right (St: String; Len: Integer): String;
  998.  
  999. Another extraction routine is more interesting. It allows you to
  1000. extract a substring from a string which contains delimited
  1001. information. For instance, consider the following name and
  1002. address string. It has three fields, each separated by an
  1003. asterisk. We can use Extract to grab any individual field:
  1004.  
  1005. St := 'Tom Hanlin*3544 E. Southern Ave. #104*Mesa, AZ 85204';
  1006. FOR PrtAddress := 1 TO 3 DO BEGIN
  1007.    AddressLine := Extract(St, '*', PrtAddress);
  1008.    WriteLn(AddressLine);
  1009. END;
  1010.  
  1011. The extract function is defined as follows:
  1012.  
  1013. FUNCTION Extract (St, Delimiter: String;
  1014.                   Index: Integer): String;
  1015.  
  1016. If you try to extract a field which doesn't exist, a null string
  1017. will be returned. Field delimiters may be anything at all, by
  1018. the way-- one possible use for Extract might be to block-read a
  1019. text file, splitting it apart in memory by using the carriage
  1020. return and linefeed as a delimiter.
  1021.  
  1022.                        String Stuff                     page 22
  1023.  
  1024.                        Unit: Strings
  1025.  
  1026.  
  1027.  
  1028. PasWiz provides an assortment of string search routines. One is
  1029. a simple modification of Pos which allows you to start the
  1030. search at a given place in the string:
  1031.  
  1032. FUNCTION Instr (Start: Integer; SubSt, St: String): Integer;
  1033.  
  1034. Another works like Pos, but returns the last match rather than
  1035. the first match:
  1036.  
  1037. FUNCTION RPos (SubSt, St: String): Integer;
  1038.  
  1039. Of course, you don't always want to search for something in
  1040. specific. You might be more interested in finding the first
  1041. character that fits into a given category or categories, like
  1042. perhaps numbers or letters. No problem:
  1043.  
  1044. FUNCTION TypePos (ChType: Integer; St: String): Integer;
  1045.  
  1046. The ChType value is formed by adding the numbers which represent
  1047. the desired categories. This can also be used to search for the
  1048. first character which is not of a given type, since the
  1049. categories are exclusive:
  1050.  
  1051.     1    alphabetic
  1052.     2    numeric
  1053.     4    symbols
  1054.     8    control codes (ASCII 0-31, 127)
  1055.    16    graphics codes (ASCII 128-255)
  1056.    32    space (ASCII 32)
  1057.  
  1058. That covers the string routines which can be readily
  1059. categorized. Most of the remaining routines are designed to
  1060. alter a string in one way or another. This includes being able
  1061. to remove selected characters, substrings, types of characters,
  1062. or repeated characters from a string; trimming the left or right
  1063. side of a string of blanks; converting to uppercase, lowercase,
  1064. or using the correct capitalization for a proper name; replacing
  1065. one substring with another; reversing a string; and forming a
  1066. new string by repeating a given substring.
  1067.  
  1068. The "case", "trim", and "reverse" functions are pretty much
  1069. self-explanatory:
  1070.  
  1071. FUNCTION LowerCase (St: String): String;    { lowercase }
  1072.  
  1073. FUNCTION NameCase (St: String): String;     { name case }
  1074.  
  1075. FUNCTION UpperCase (St: String): String;    { upper case }
  1076.  
  1077. FUNCTION LTrim (St: String): String;        { left trim }
  1078.  
  1079. FUNCTION RTrim (St: String): String;        { right trim }
  1080.  
  1081. FUNCTION Reverse (St: String): String;      { reverse }
  1082.  
  1083.                        String Stuff                     page 23
  1084.  
  1085.                        Unit: Strings
  1086.  
  1087.  
  1088.  
  1089. The Crunch function removes adjacent repetitions of a substring.
  1090. This is particularly handy for parsing user input, for example--
  1091. you can use it to remove repeated spaces between options, etc.
  1092.  
  1093. FUNCTION Crunch (SubSt, St: String): String;
  1094.  
  1095. The Dupe function forms a string by repeating a substring. It's
  1096. handy when you need a string of a given number of spaces,
  1097. zeroes, or nulls. It can also be used for drawing horizontal
  1098. lines and other applications.
  1099.  
  1100. FUNCTION Dupe (Count: Integer; SubSt: String): String;
  1101.  
  1102. There are many times when it's nice to be able to replace all
  1103. occurrences of one substring with another. PasWiz can do that,
  1104. no problem. You don't have to worry about recursion, either--
  1105. each occurrence is replaced only once, even if the replacement
  1106. substring contains the target substring.
  1107.  
  1108. FUNCTION Replace (OldSubSt, NewSubSt, St: String): String;
  1109.  
  1110. Of course, you can delete a substring by replacing it with a
  1111. null string. It's faster to use the routine designed for that
  1112. purpose, though:
  1113.  
  1114. FUNCTION StripSt (SubSt, St: String): String;
  1115.  
  1116. You may also delete specified characters from a string:
  1117.  
  1118. FUNCTION StripCh (ChList, St: String): String;
  1119.  
  1120. Next, a routine which deletes specified types of characters from
  1121. a string. This can be very good for screening user input.
  1122.  
  1123. FUNCTION StripType (ChType: Integer; St: String): String;
  1124.  
  1125. The ChType value is formed by adding the numbers which represent
  1126. the desired categories:
  1127.  
  1128.     1    alphabetic
  1129.     2    numeric
  1130.     4    symbols
  1131.     8    control codes (ASCII 0-31, 127)
  1132.    16    graphics codes (ASCII 128-255)
  1133.    32    space (ASCII 32)
  1134.  
  1135. PasWiz also has a specialized variant on the Val function which
  1136. converts a number from a string to a WORD (or INTEGER) value. No
  1137. error checking is provided. This is very small and fast:
  1138.  
  1139.    FUNCTION WVal (St: STRING): WORD;
  1140.  
  1141.                             Music                       page 24
  1142.  
  1143.                          Unit: Music
  1144.  
  1145.  
  1146.  
  1147. Granted, the PC has never been known for its wonderful sound
  1148. capabilities. Still, it has more potential than you might guess,
  1149. especially given the utterly minimal Sound/Delay/NoSound
  1150. routines that are provided with Pascal. The Music unit makes it
  1151. much easier to use sounds by providing an actual music language.
  1152. The BACHINV and ENTERTNR demo programs demonstrate some of the
  1153. possibilities.
  1154.  
  1155. The PasWiz music language is nearly identical to that offered by
  1156. the BASIC PLAY statement. The major difference is that the "MB"
  1157. command (play the music as a background task) is not supported.
  1158. I'll add that later, if I get enough requests.
  1159.  
  1160. There are only two music procedures:
  1161.  
  1162. PROCEDURE ResetMF;
  1163.  
  1164. PROCEDURE PlayMF(Sounds: String);
  1165.  
  1166. The ResetMF procedure is used to reset all music parameters to
  1167. the default values. It would typically be used after finishing a
  1168. song to restore the music handler for the next song.
  1169.  
  1170. The PlayMF procedure is the one that does the real work. Here's
  1171. a list of the music commands supported:
  1172.  
  1173.    MB  play music as a background task (ignored)
  1174.    MF  play music as a foreground task (ignored)
  1175.    ML  legato (8/8 note length)
  1176.    MN  normal music (7/8 note length)
  1177.    MN  staccato (6/8 note length)
  1178.    Ln  Length of notes (n = 1-64; note length = 1/n)
  1179.    Nn  Note number (n = 0-84; 0 is a rest)
  1180.    On  Octave (n = 0-6, default 4)
  1181.    Pn  Pause (n = 1-64; pause length = 1/n)
  1182.    Tn  Tempo (n = 32-255, default 120; quarter notes/minute)
  1183.    <   move up an octave (max 6)
  1184.    >   move down an octave (min 0)
  1185.  
  1186. You can also use the actual letters of the notes (C, D, E, F, G,
  1187. A, and B). If you're not particularly musical, these correspond
  1188. to "do, re, mi, fa, so, la, ti" (with the final "do" being C
  1189. again, but an octave higher). To play a scale, you'd use
  1190. 'CDEFGAB>C'. The notes may be followed by dots, by note lengths,
  1191. and by sharp or flat symbols (a '+' or '#' for a sharp, a '-'
  1192. for a flat). For example, 'D-.' is a dotted D flat. The dot
  1193. means that the note will play for half again its usual length.
  1194. Dots can be repeated.
  1195.  
  1196. I might note (ahem) that the so-called "ANSI" music offered by
  1197. some BBSes and comm programs is based on this same music
  1198. language. If you're writing telecomm software, this unit makes
  1199. it trivial to add sound.
  1200.  
  1201.                             Mouse                       page 25
  1202.  
  1203.                          Unit: Mouse
  1204.  
  1205.  
  1206.  
  1207. Considering the ubiquity of the mouse these days, it's a marvel
  1208. to me that none of the popular programming languages provides
  1209. any support for it. Well, BASIC supports it via light pen
  1210. emulation, but that scarcely counts. Anyway, this is a simple
  1211. little unit which provides you direct access to the mouse
  1212. driver. It will work with any Microsoft-compatible mouse driver.
  1213.  
  1214. A few words are necessary on mouse handling. To begin with, the
  1215. best time to check for a mouse is immediately after you've
  1216. established the desired video mode. The mouse driver initializes
  1217. certain information when you check for it, so it's a good idea
  1218. to check for it only once, at the appropriate time.
  1219.  
  1220. The mouse cursor was implemented in a rather bizarre manner. If
  1221. you call ShowCursor, you're guaranteed that the mouse cursor
  1222. will be visible; however, this also increments an internal
  1223. visibility flag. If you call ShowCursor multiple times, you will
  1224. also have to call HideCursor multiple times before the dang
  1225. cursor actually disappears.
  1226.  
  1227. The mouse driver was apparently implemented without any thought
  1228. for the future. In text mode, it returns coordinates based on
  1229. CGA hi-res graphics mode-- 640x200 instead of the expected
  1230. 80x25. If you use the mouse driver in text mode, you'll have to
  1231. compensate for this (divide coordinates by 8 to convert to text
  1232. mode, or multiply by 8 to convert to the mouse virtual mode).
  1233. The CGA low-res 320x200 graphics mode is implemented likewise.
  1234. It seems Microsoft thought that 640x200 would be the ultimate
  1235. resolution, so they translated everything to a 640x200 virtual
  1236. mode. Arrgh. Fortunately, this does not apply to video modes
  1237. other than text and CGA graphics.
  1238.  
  1239. I understand that it's possible to get the mouse working in
  1240. Hercules graphics mode, but I'm not sure what the details are.
  1241. If anyone out there knows, please let me know, and I'll pass it
  1242. along.
  1243.  
  1244. Since Microsoft was initially very tight-lipped about the mouse
  1245. functions, older mouse drivers for Microsoft-compatible rodents
  1246. don't necessarily have all the functions available (this
  1247. includes Logitech, amazingly enough). The Microsoft mouse driver
  1248. continues to be updated in a rapid and haphazard manner, so
  1249. keeping up-to-date is no guarantee. However, if you have any
  1250. problems with these routines, you can almost certainly clear
  1251. them up by getting a newer mouse driver. The routines in this
  1252. unit are almost all old, well-established functions. "Iffy" ones
  1253. are marked for your convenience.
  1254.  
  1255.                             Mouse                       page 26
  1256.  
  1257.                          Unit: Mouse
  1258.  
  1259.  
  1260.  
  1261. The first function to consider simply tells you whether a mouse
  1262. is available, and if so, how many buttons it has. It also resets
  1263. the mouse driver, so it should be used only at the beginning of
  1264. your program (or after changing the video mode).
  1265.  
  1266. FUNCTION Init: Integer;
  1267.    { returns 0 if no mouse, else # of buttons }
  1268.  
  1269. Most often, you'll want to know which mouse button(s) are
  1270. pressed and where the mouse cursor is:
  1271.  
  1272. FUNCTION LeftButton: Boolean;
  1273.    { TRUE if pressed }
  1274.  
  1275. FUNCTION MidButton: Boolean;
  1276.    { always FALSE on 2-button rodents }
  1277.  
  1278. FUNCTION RightButton: Boolean;
  1279.    { TRUE if pressed }
  1280.  
  1281. FUNCTION WhereX: Integer;
  1282.    { X-coord (see notes on previous page) }
  1283.  
  1284. FUNCTION WhereY: Integer;
  1285.    { Y-coord (see notes on previous page) }
  1286.  
  1287. As well as finding the current mouse information, it's possible
  1288. to find out what the mouse has been doing since you last
  1289. checked. Two sets of routines exist: one to find out how many
  1290. times a button was pressed and where it was at the last press,
  1291. and one to find out how many times a button was released and
  1292. where it was at the last release.
  1293.  
  1294. PROCEDURE LeftClick(VAR Count, X, Y: Integer);
  1295.  
  1296. PROCEDURE MidClick(VAR Count, X, Y: Integer);
  1297.  
  1298. PROCEDURE RightClick(VAR Count, X, Y: Integer);
  1299.  
  1300. PROCEDURE LeftRelease(VAR Count, X, Y: Integer);
  1301.  
  1302. PROCEDURE MidRelease(VAR Count, X, Y: Integer);
  1303.  
  1304. PROCEDURE RightRelease(VAR Count, X, Y: Integer);
  1305.  
  1306.                             Mouse                       page 27
  1307.  
  1308.                          Unit: Mouse
  1309.  
  1310.  
  1311.  
  1312. There's one more informational routine. It tells you the basic
  1313. mouse software and hardware stats: driver version, connector
  1314. type (serial, bus, etc), and IRQ used. This routine is slightly
  1315. hazardous in that, although Microsoft claims it has existed from
  1316. the first, other manufacturers (including Logitech) have taken
  1317. some time to implement it. In other words, it may not return
  1318. useful information. The routine conducts a self-check and will
  1319. return all zeroes if it suspects the information is not good,
  1320. but even so... proceed with care.
  1321.  
  1322. PROCEDURE Info(VAR Version: Real; VAR Connector, IRQ: Byte);
  1323.  
  1324. Connector info: 1=bus, 2=serial, 3=InPort, 4=PS/2,
  1325. 5=Hewlett-Packard IRQs: 0=PS/2; 2-5, 7 are actual IRQ numbers.
  1326. It is conceivable that higher IRQ numbers may be supported on
  1327. AT-type machines, though not by Microsoft.
  1328.  
  1329. Of course, you can set mouse info as well as retrieving it. The
  1330. following routines are pretty well self-explanatory (don't
  1331. forget the notes about the strange text-mode and CGA coordinate
  1332. handling, and cursor handling):
  1333.  
  1334. { hide the mouse cursor }
  1335. PROCEDURE HideCursor;
  1336.  
  1337. { (maybe) make the cursor visible }
  1338. PROCEDURE ShowCursor;
  1339.  
  1340. { set the cursor position }
  1341. PROCEDURE GotoXY(X, Y: Integer);
  1342.  
  1343. { set the cursor range }
  1344. PROCEDURE Window(X1, Y1, X2, Y2: Integer);
  1345.  
  1346. There are other possibilities supported by the mouse driver that
  1347. I have not implemented here. They're mostly on the rather
  1348. esoteric side and are not supported by anything except recent
  1349. Microsoft mouse drivers and perhaps some close compatibles, such
  1350. as Logitech.
  1351.  
  1352. Among the mouse capabilities I haven't implemented are finding
  1353. out how fast and in what direction the mouse is moving, the
  1354. coordinate size of the screen as far as the mouse is concerned,
  1355. finding out the video modes that the mouse driver understands,
  1356. setting mouse speed and sensitivity parameters, setting up an
  1357. interrupt-driven system for handling mouse events, and a few
  1358. others.
  1359.  
  1360.                             Mouse                       page 28
  1361.  
  1362.                          Unit: Mouse
  1363.  
  1364.  
  1365.  
  1366. None of these missing capabilities is particularly vital (or
  1367. even useful) for the average mouse application. However, if
  1368. you're interested in any of these capabilities, let me know
  1369. which ones, and I'll be glad to add them to PasWiz.
  1370.  
  1371. Note: if you're confused at how I can get away with duplicating
  1372. the names of existing procedures... well, it's easy enough.
  1373. Let's consider WhereX. It means one thing to Pascal's Crt unit
  1374. and another to the PasWiz Mouse unit. Since the Mouse unit
  1375. doesn't use the Crt unit, it has no problem with any ambiguity.
  1376. Existing programs that don't use the Mouse unit will likewise
  1377. have no problems, since they don't know about the new routine.
  1378. Suppose you want to use both the Crt and Mouse units together,
  1379. however? There's the rub!
  1380.  
  1381. You can specify a routine from a given unit by including the
  1382. unit name when you use the routine. For instance:
  1383.  
  1384. X := Mouse.WhereX;      { get the mouse cursor position }
  1385.  
  1386. X := Crt.WhereX;        { get the normal cursor position }
  1387.  
  1388. This allows multiple units to use the same names for things.
  1389. While this may seem like a bit of a pain, since you have to
  1390. specify which you want, it has a major built-in advantage if
  1391. used properly. What's properly? When a routine in one unit works
  1392. just like a routine by the same name in another unit. When I
  1393. call the mouse routine "WhereX", for instance, I've also told
  1394. you what it is for and how to use it. So, the name itself
  1395. contains a lot of useful information on how to use the routine!
  1396. That's what I call a major advantage.
  1397.  
  1398.